package com.carbeauty.entity;

import com.carbeauty.common.entity.BaseEntity;
import com.carbeauty.common.enums.PaymentMethod;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.persistence.*;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

import java.math.BigDecimal;
import java.time.LocalDateTime;

/**
 * 充值记录实体类
 * 
 * 充值余额管理功能:
 * - 客户充值记录
 * - 充值金额管理
 * - 赠送金额管理
 * - 支付方式记录
 * - 操作员记录
 * 
 * @author CarBeauty Team
 */
@Entity
@Table(name = "cb_recharge_record")
public class RechargeRecord extends BaseEntity {
    
    /**
     * 客户ID - 不使用外键约束
     */
    @NotNull(message = "客户ID不能为空")
    @Column(name = "customer_id", nullable = false)
    private Long customerId;
    
    /**
     * 客户姓名 - 冗余字段，便于查询
     */
    @Size(max = 50, message = "客户姓名长度不能超过50个字符")
    @Column(name = "customer_name", length = 50)
    private String customerName;
    
    /**
     * 客户手机号 - 冗余字段，便于查询
     */
    @Size(max = 11, message = "手机号长度不能超过11个字符")
    @Column(name = "customer_phone", length = 11)
    private String customerPhone;
    
    /**
     * 充值金额
     */
    @NotNull(message = "充值金额不能为空")
    @DecimalMin(value = "0.01", message = "充值金额必须大于0")
    @Column(name = "recharge_amount", nullable = false, precision = 10, scale = 2)
    private BigDecimal rechargeAmount;
    
    /**
     * 赠送金额
     */
    @DecimalMin(value = "0", message = "赠送金额不能为负数")
    @Column(name = "bonus_amount", precision = 10, scale = 2)
    private BigDecimal bonusAmount = BigDecimal.ZERO;
    
    /**
     * 实际到账金额 (充值金额 + 赠送金额)
     */
    @NotNull(message = "到账金额不能为空")
    @DecimalMin(value = "0.01", message = "到账金额必须大于0")
    @Column(name = "actual_amount", nullable = false, precision = 10, scale = 2)
    private BigDecimal actualAmount;
    
    /**
     * 充值前余额
     */
    @DecimalMin(value = "0", message = "充值前余额不能为负数")
    @Column(name = "balance_before", precision = 10, scale = 2)
    private BigDecimal balanceBefore = BigDecimal.ZERO;
    
    /**
     * 充值后余额
     */
    @DecimalMin(value = "0", message = "充值后余额不能为负数")
    @Column(name = "balance_after", precision = 10, scale = 2)
    private BigDecimal balanceAfter = BigDecimal.ZERO;
    
    /**
     * 支付方式
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "payment_method", length = 20)
    private PaymentMethod paymentMethod;
    
    /**
     * 充值时间
     */
    @NotNull(message = "充值时间不能为空")
    @Column(name = "recharge_date", nullable = false)
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime rechargeDate;
    
    /**
     * 操作员ID - 不使用外键约束
     */
    @Column(name = "operator_id")
    private Long operatorId;
    
    /**
     * 操作员姓名 - 冗余字段
     */
    @Size(max = 50, message = "操作员姓名长度不能超过50个字符")
    @Column(name = "operator_name", length = 50)
    private String operatorName;
    
    /**
     * 充值渠道
     */
    @Size(max = 50, message = "充值渠道长度不能超过50个字符")
    @Column(name = "recharge_channel", length = 50)
    private String rechargeChannel = "门店充值";
    
    /**
     * 充值活动ID - 如果参与充值活动
     */
    @Column(name = "activity_id")
    private Long activityId;
    
    /**
     * 充值活动名称 - 冗余字段
     */
    @Size(max = 100, message = "活动名称长度不能超过100个字符")
    @Column(name = "activity_name", length = 100)
    private String activityName;
    
    /**
     * 交易流水号
     */
    @Size(max = 64, message = "交易流水号长度不能超过64个字符")
    @Column(name = "transaction_no", length = 64)
    private String transactionNo;
    
    /**
     * 充值备注
     */
    @Size(max = 200, message = "充值备注长度不能超过200个字符")
    @Column(name = "recharge_remark", length = 200)
    private String rechargeRemark;
    
    // ==================== 构造方法 ====================
    
    public RechargeRecord() {
        super();
        this.rechargeDate = LocalDateTime.now();
    }
    
    public RechargeRecord(Long customerId, String customerName, String customerPhone, 
                         BigDecimal rechargeAmount, BigDecimal bonusAmount) {
        this();
        this.customerId = customerId;
        this.customerName = customerName;
        this.customerPhone = customerPhone;
        this.rechargeAmount = rechargeAmount;
        this.bonusAmount = bonusAmount != null ? bonusAmount : BigDecimal.ZERO;
        this.calculateActualAmount();
    }
    
    // ==================== Getter/Setter ====================
    
    public Long getCustomerId() {
        return customerId;
    }
    
    public void setCustomerId(Long customerId) {
        this.customerId = customerId;
    }
    
    public String getCustomerName() {
        return customerName;
    }
    
    public void setCustomerName(String customerName) {
        this.customerName = customerName;
    }
    
    public String getCustomerPhone() {
        return customerPhone;
    }
    
    public void setCustomerPhone(String customerPhone) {
        this.customerPhone = customerPhone;
    }
    
    public BigDecimal getRechargeAmount() {
        return rechargeAmount;
    }
    
    public void setRechargeAmount(BigDecimal rechargeAmount) {
        this.rechargeAmount = rechargeAmount;
        this.calculateActualAmount();
    }
    
    public BigDecimal getBonusAmount() {
        return bonusAmount;
    }
    
    public void setBonusAmount(BigDecimal bonusAmount) {
        this.bonusAmount = bonusAmount;
        this.calculateActualAmount();
    }
    
    public BigDecimal getActualAmount() {
        return actualAmount;
    }
    
    public void setActualAmount(BigDecimal actualAmount) {
        this.actualAmount = actualAmount;
    }
    
    public BigDecimal getBalanceBefore() {
        return balanceBefore;
    }
    
    public void setBalanceBefore(BigDecimal balanceBefore) {
        this.balanceBefore = balanceBefore;
    }
    
    public BigDecimal getBalanceAfter() {
        return balanceAfter;
    }
    
    public void setBalanceAfter(BigDecimal balanceAfter) {
        this.balanceAfter = balanceAfter;
    }
    
    public PaymentMethod getPaymentMethod() {
        return paymentMethod;
    }
    
    public void setPaymentMethod(PaymentMethod paymentMethod) {
        this.paymentMethod = paymentMethod;
    }
    
    public LocalDateTime getRechargeDate() {
        return rechargeDate;
    }
    
    public void setRechargeDate(LocalDateTime rechargeDate) {
        this.rechargeDate = rechargeDate;
    }
    
    public Long getOperatorId() {
        return operatorId;
    }
    
    public void setOperatorId(Long operatorId) {
        this.operatorId = operatorId;
    }
    
    public String getOperatorName() {
        return operatorName;
    }
    
    public void setOperatorName(String operatorName) {
        this.operatorName = operatorName;
    }
    
    public String getRechargeChannel() {
        return rechargeChannel;
    }
    
    public void setRechargeChannel(String rechargeChannel) {
        this.rechargeChannel = rechargeChannel;
    }
    
    public Long getActivityId() {
        return activityId;
    }
    
    public void setActivityId(Long activityId) {
        this.activityId = activityId;
    }
    
    public String getActivityName() {
        return activityName;
    }
    
    public void setActivityName(String activityName) {
        this.activityName = activityName;
    }
    
    public String getTransactionNo() {
        return transactionNo;
    }
    
    public void setTransactionNo(String transactionNo) {
        this.transactionNo = transactionNo;
    }
    
    public String getRechargeRemark() {
        return rechargeRemark;
    }
    
    public void setRechargeRemark(String rechargeRemark) {
        this.rechargeRemark = rechargeRemark;
    }
    
    // ==================== 业务方法 ====================
    
    /**
     * 计算实际到账金额
     */
    public void calculateActualAmount() {
        if (rechargeAmount != null) {
            BigDecimal bonus = bonusAmount != null ? bonusAmount : BigDecimal.ZERO;
            this.actualAmount = rechargeAmount.add(bonus);
        }
    }
    
    /**
     * 计算余额变化
     */
    public void calculateBalanceChange(BigDecimal beforeBalance) {
        this.balanceBefore = beforeBalance;
        this.balanceAfter = beforeBalance.add(actualAmount);
    }
    
    /**
     * 生成交易流水号
     */
    public void generateTransactionNo() {
        if (this.transactionNo == null || this.transactionNo.isEmpty()) {
            // 格式: RC + 年月日时分秒 + 6位随机数
            String timestamp = LocalDateTime.now()
                .format(java.time.format.DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
            String random = String.format("%06d", (int)(Math.random() * 1000000));
            this.transactionNo = "RC" + timestamp + random;
        }
    }
    
    /**
     * 检查是否有赠送金额
     */
    public boolean hasBonus() {
        return bonusAmount != null && bonusAmount.compareTo(BigDecimal.ZERO) > 0;
    }
    
    /**
     * 获取赠送比例
     */
    public BigDecimal getBonusRate() {
        if (hasBonus() && rechargeAmount.compareTo(BigDecimal.ZERO) > 0) {
            return bonusAmount.divide(rechargeAmount, 4, BigDecimal.ROUND_HALF_UP);
        }
        return BigDecimal.ZERO;
    }
    
    /**
     * 获取赠送百分比
     */
    public BigDecimal getBonusPercentage() {
        return getBonusRate().multiply(new BigDecimal("100"));
    }
}
